package com.party.api.service.wechatPlatform.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.party.api.dto.wechatPlatform.requst.RefreshAuthorizerTokenRequest;
import com.party.api.dto.wechatPlatform.response.Oauth2AccessTokenResponse;
import com.party.api.dto.wechatPlatform.response.RefreshAuthorizerTokenResponse;
import com.party.api.dto.wechatPlatform.response.WechatAuthorizerInfoResponse;
import com.party.api.dto.wechatPlatform.response.WechatAuthorizerUserInfoResponse;
import com.party.api.service.wechatPlatform.IWechatPlatformService;
import com.party.api.utils.WechatPlateformConstent;
import com.party.common.constant.Constant;
import com.party.common.constant.WechatConstant;
import com.party.common.utils.wechat.WechatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * 第三方平台接口实现
 * Created by wei.li
 *
 * @date 2017/8/26 0026
 * @time 10:12
 */
@Service
public class WechatPlatformService implements IWechatPlatformService {


    protected static Logger logger = LoggerFactory.getLogger(WechatPlatformService.class);

    private static final String COMPONENT_ACCESS_TOKEN = "COMPONENT_ACCESS_TOKEN";

    private static final String COMPONENT_APPID = "COMPONENT_APPID";

    private static final String APPID = "APPID";

    private static final String CODE = "CODE";

    /**
     * 获取第三方平台交互令牌
     * @param appid 第三方平台appid
     * @param appsecret 第三方平台appsecret
     * @param verifyTicket 微信后台推送的ticket，此ticket会定时推送
     * @return 交互令牌
     */
    @Override
    public String getAccessToken(String appid, String appsecret, String verifyTicket) {
        Map<String, Object> requestMap = Maps.newHashMap();
        requestMap.put("component_appid", appid);
        requestMap.put("component_appsecret", appsecret);
        requestMap.put("component_verify_ticket", verifyTicket);

        String url = WechatPlateformConstent.COMPONENT_TOKEN_URL;

        logger.info("获取第三方交互令牌请求报文{}", JSONObject.toJSONString(requestMap));
        JSONObject jsonObject = WechatUtils.httpRequest(url, WechatUtils.POST, JSONObject.toJSONString(requestMap));
        logger.info("获取第三方交互令牌响应报文{}", jsonObject.toJSONString());

        Map responseMap = JSONObject.toJavaObject(jsonObject, Map.class);
        return (String) responseMap.get("component_access_token");
    }

    /**
     * 获取预授权码
     * @param appid 第三方平台方appid
     * @param accessToken 第三方平台access_token
     * @return 预授权码
     */
    @Override
    public String getPreAuthCode(String appid, String accessToken) {

        Map<String, Object> requestMap = Maps.newHashMap();
        requestMap.put("component_appid", appid);
        String url = WechatPlateformConstent.PRE_AUTH_CODE_URL.replace("{0}", accessToken);

        logger.info("获取预授权码请求报文{}", JSONObject.toJSONString(requestMap));
        JSONObject jsonObject = WechatUtils.httpRequest(url, WechatUtils.POST, JSONObject.toJSONString(requestMap));
        logger.info("获取预授权码响应报文{}", jsonObject.toJSONString());

        Map responseMap = JSONObject.toJavaObject(jsonObject, Map.class);
        return (String) responseMap.get("pre_auth_code");
    }

    /**
     * 获取用户授权连接
     * @param redirectUrl 重定向地址
     * @param componentAppid 第三方平台appid
     * @param authCode 预授权码
     * @return 授权连接
     * @throws UnsupportedEncodingException
     */
    @Override
    public String getAuthorizeUrl(String redirectUrl, String componentAppid,
                                  String authCode) throws UnsupportedEncodingException {
        redirectUrl = URLEncoder.encode(redirectUrl, Constant.UTF_8);
        authCode =  URLEncoder.encode(authCode, Constant.UTF_8);
        String url = WechatPlateformConstent.GET_AUTHORIZE_URL.replace("APPID", componentAppid)
                .replace("AUTH_CODE", authCode)
                .replace("REDIRECT_URI", redirectUrl);
        return url;
    }

    /**
     * 获取授权信息
     * @param componentAppid 第三方平台appid
     * @param componentAccessToken 第三方平台access_token
     * @param authorizationCode 授权code
     * @return 授权信息
     */
    @Override
    public WechatAuthorizerInfoResponse getAuthorizationInfo(String componentAppid,
                                                             String componentAccessToken, String authorizationCode) {
        Map<String, Object> requestMap = Maps.newHashMap();
        requestMap.put("component_appid", componentAppid);
        requestMap.put("authorization_code", authorizationCode);

        String url = WechatPlateformConstent.AUTHORIZATION_INFO_URL.replace("{0}", componentAccessToken);

        logger.info("获取授权信息请求报文{}", JSONObject.toJSONString(requestMap));
        String jsonObject = WechatUtils.httpRequestStr(url, WechatUtils.POST, JSONObject.toJSONString(requestMap));
        logger.info("获取授权信息响应报文{}", jsonObject);

        WechatAuthorizerInfoResponse authorizationInfo = JSONObject.parseObject(jsonObject, WechatAuthorizerInfoResponse.class);
        return authorizationInfo;
    }

    /**
     * 刷新授权方令牌
     * @param request 请求参数
     * @param componentAccessToken 第三方平台令牌
     * @return 响应参数
     */
    @Override
    public RefreshAuthorizerTokenResponse refreshAuthorizerToken(RefreshAuthorizerTokenRequest request,
                                                                 String componentAccessToken) {
        checkNotNull(request,"请求参数不能为空");
        checkNotNull(componentAccessToken,"第三方平台令牌不能为空");

        String requestUrl
                = WechatPlateformConstent.REFRESH_AUTHORIZER_TOKEN_URL.replace(COMPONENT_ACCESS_TOKEN, componentAccessToken);

        logger.info("刷新授权方令牌请求参数{}", JSONObject.toJSONString(request));
        JSONObject response
                = WechatUtils.httpRequest(requestUrl, WechatConstant.POST,  JSONObject.toJSONString(request));
        logger.info("刷新授权方令牌响应参数{}", response.toJSONString());

        return JSONObject.toJavaObject(response, RefreshAuthorizerTokenResponse.class);
    }

    /**
     * 获取授权令牌
     * @param appId 公众号 appid
     * @param code 授权码
     * @param componentAppid 开放平台 appid
     * @param componentAccessToken 开放平台 交互令牌
     * @return 响应参数
     */
    @Override
    public Oauth2AccessTokenResponse getOauth2AccessToken(String appId, String code,
                                                          String componentAppid, String componentAccessToken) {
        checkNotNull(appId, "公众号不能为空");
        checkNotNull(code, "授权码不能为空");
        checkNotNull(componentAppid, "开放平台appid不能为空");
        checkNotNull(componentAccessToken, "公众平台交互令牌不能为空");

        String requestUrl = WechatPlateformConstent.OAUTH2_ACCESS_TOKEN_URL
                .replace(COMPONENT_ACCESS_TOKEN, componentAccessToken)
                .replace(COMPONENT_APPID, componentAppid)
                .replace(APPID, appId)
                .replace(CODE, code);

        logger.info("获取授权令牌请求参数{}", requestUrl);
        JSONObject response = WechatUtils.httpRequest(requestUrl, WechatConstant.GET, null);
        logger.info("获取授权令牌响应参数{}", response.toJSONString());

        return JSONObject.toJavaObject(response, Oauth2AccessTokenResponse.class);
    }

    /**
     * 获取授权方的帐号基本信息
     * @param componentAppid 服务appid
     * @param authorizerAppid 授权方appid
     * @param componentAccessToken 第三方平台access_token
     * @return 授权方基本信息
     */
    @Override
    public WechatAuthorizerUserInfoResponse getAuthorizerInfo(String componentAppid,
                                                              String authorizerAppid, String componentAccessToken) {
        Map<String, Object> params = Maps.newHashMap();
        params.put("component_appid", componentAppid);
        params.put("authorizer_appid", authorizerAppid);
        String url = WechatPlateformConstent.AUTHORIZER_INFO_URL.replace("{0}", componentAccessToken);

        logger.info("获取授权方基本信息请求报文{}", JSONObject.toJSONString(params));
        String response = WechatUtils.httpRequestStr(url, WechatUtils.POST, JSONObject.toJSONString(params));
        logger.info("获取授权方基本信息响应报文{}", response);

        return JSONObject.parseObject(response, WechatAuthorizerUserInfoResponse.class);
    }
}
